# coding: UTF-8
# -*- coding: UTF-8 -*-
import threading
from threading import Thread
import struct
import time
import hashlib
import base64
import socket
import mainget_data
import inspect
import ctypes


# 关闭线程
def _async_raise(tid, exctype):
    """raises the exception, performs cleanup if needed"""
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")


# 循环定时执行

timeleft = 0


# 真正要执行的函数
def counttime():
    global timeleft
    # print('timeleft::'+str(timeleft))
    timeleft = timeleft - 1


# 每隔1秒钟执行
def ReRunFuc():
    while (timeleft != 0):
        counttime()
        time.sleep(1)
        # print(threading.currentThread().name)
        # print(threading.currentThread().ident)
    print("thread closed")
    # writeJson('UserID', 'UserEmail', 'UserIP')
    _async_raise(threading.currentThread().ident, SystemExit)


def reCount():
    print("reCUONTing")
    global timeleft
    timeleft = 60
    # t4.join()
    t4 = threading.Thread(target=ReRunFuc)
    t4.start()


mode = "initialize"
pic_size = 0
pic_receive = 0
pic = ""
pic_repeat = []
receiveddata = ''


class returnCrossDomain(Thread):

    def __init__(self, connection):
        Thread.__init__(self)
        self.con = connection
        self.isHandleShake = False

    def run(self):
        global mode
        global pic_size
        global pic_receive
        global pic
        global pic_repeat
        global receiveddata
        while True:
            if not self.isHandleShake:
                # 开始握手阶段
                header = self.analyzeReq()
                secKey = header['Sec-WebSocket-Key'];
                acceptKey = self.generateAcceptKey(secKey)
                response = "HTTP/1.1 101 Switching Protocols\r\n"
                response += "Upgrade: websocket\r\n"
                response += "Connection: Upgrade\r\n"
                response += "Sec-WebSocket-Accept: %s\r\n\r\n" % (acceptKey.decode('utf-8'))
                self.con.send(response.encode())
                self.isHandleShake = True
                if (mode == "initialize"):
                    mode = "get_order"
                print('response:' + response[75:127])
                # 握手阶段结束
                # 读取命令阶段
            elif mode == "get_order":
                opcode = self.getOpcode()
                if opcode == 8:
                    self.con.close()
                self.getDataLength()
                clientData = self.readClientData()
                print('客户端数据：' + str(clientData))

                # 处理数据-----------------------------------------------------------
                result = str(clientData)  # ''.join(data)

                if result[:4] == '?ID=':
                    print('recive id ,return url')
                    temp_str0 = result.replace('?ID=', '')
                    temp_str0 = temp_str0.replace(' \r', '')
                    toClientData = mainget_data.get_URL(str(temp_str0))

                elif result[:5] == '?URL=':
                    if (timeleft == 0):
                        print("timeleft == 0")
                        reCount()

                        print('recive url ,add id,return short url')
                        temp_str0 = result.replace('?URL=', '')
                        toClientData = mainget_data.add_json(temp_str0)
                    else:
                        print("计时ing")
                        ttt = str(timeleft)
                        toClientData = str('waiting for ' + ttt + ' seconds')
                        print('timeleft:' + str(timeleft))

                else:
                    print('error require' + result)
                    toClientData = 'server: error require: ' + result + '\r\n'

                ssss = str(toClientData)
                self.sendDataToClient(ssss)




                # 处理数据

    def legal(self, string):  # python总会胡乱接收一些数据。。只好过滤掉
        if len(string) == 0:
            return 0
        elif len(string) <= 100:
            if self.loc(string) != len(string):
                return 0
            else:
                if mode != "get_pic":
                    return 1
                elif len(string) + pic_receive == pic_size:
                    return 1
                else:
                    return 0
        else:
            if self.loc(string) > 100:
                if mode != "get_pic":
                    return 1
                elif string[0:100] not in pic_repeat:
                    pic_repeat.append(string[0:100])
                    return 1
                else:
                    return -1  # 收到重复数据，需要重定位
            else:
                return 0

    def loc(self, string):
        i = 0
        while (i < len(string) and self.rightbase64(string[i])):
            i = i + 1
        return i

    def rightbase64(self, ch):
        if (ch >= "a") and (ch <= "z"):
            return 1
        elif (ch >= "A") and (ch <= "Z"):
            return 1
        elif (ch >= "0") and (ch <= "9"):
            return 1
        elif ch == '+' or ch == '/' or ch == '|' or ch == '=' or ch == ' ' or ch == "'" or ch == '!' or ch == ':':
            return 1
        else:
            return 0

    def analyzeReq(self):
        reqData = self.con.recv(1024).decode()
        reqList = reqData.split('\r\n')
        headers = {}
        for reqItem in reqList:
            if ': ' in reqItem:
                unit = reqItem.split(': ')
                headers[unit[0]] = unit[1]
        return headers

    def generateAcceptKey(self, secKey):
        sha1 = hashlib.sha1()
        sha1.update((secKey + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11').encode())
        sha1_result = sha1.digest()
        acceptKey = base64.b64encode(sha1_result)
        return acceptKey

    def getOpcode(self):
        first8Bit = self.con.recv(1)
        first8Bit = struct.unpack('B', first8Bit)[0]
        opcode = first8Bit & 0b00001111
        return opcode

    def getDataLength(self):
        second8Bit = self.con.recv(1)
        second8Bit = struct.unpack('B', second8Bit)[0]
        masking = second8Bit >> 7
        dataLength = second8Bit & 0b01111111
        # print("dataLength:",dataLength)
        if dataLength <= 125:
            payDataLength = dataLength
        elif dataLength == 126:
            payDataLength = struct.unpack('H', self.con.recv(2))[0]
        elif dataLength == 127:
            payDataLength = struct.unpack('Q', self.con.recv(8))[0]
        self.masking = masking
        self.payDataLength = payDataLength
        # print("payDataLength:", payDataLength)

    def readClientData(self):
        if self.masking == 1:
            maskingKey = self.con.recv(4)
        data = self.con.recv(self.payDataLength)
        if self.masking == 1:
            i = 0
            trueData = ''
            for d in data:
                trueData += chr(d ^ maskingKey[i % 4])
                i += 1
            return trueData
        else:
            return data

    def sendDataToClient(self, text):
        sendData = ''
        sendData = struct.pack('!B', 0x81)
        length = len(text)
        if length <= 125:
            sendData += struct.pack('!B', length)
        elif length <= 65536:
            sendData += struct.pack('!B', 126)
            sendData += struct.pack('!H', length)
        elif length == 127:
            sendData += struct.pack('!B', 127)
            sendData += struct.pack('!Q', length)
        sendData += struct.pack('!%ds' % (length), text.encode())
        dataSize = self.con.send(sendData)

    def answer(self, data):
        if ('@' in data):
            return 'EmailAdress Accepted!\r\n'
        else:
            return data

    def padding(self, data):
        missing_padding = 4 - len(data) % 4
        if missing_padding:
            data += '=' * missing_padding
        return data


def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('127.0.0.1', 9999))
    print("监听端口：9999")
    sock.listen(5)
    while True:
        try:
            connection, address = sock.accept()
            returnCrossDomain(connection).start()
        except:
            time.sleep(1)
            print("error")


if __name__ == "__main__":
    # 此处写你主线程要处理的事情.....
    main()
    # 此处写你主线程要处理的事情.....
